package echo.netty.handler_pipeline;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @author： zhangnan
 * @date： 2025/5/9 15:18
 * @description： netty解决粘包版半包问题测试类
 * @modifiedBy：
 * @version: 1.0
 */
public class TestHander {

    /**
     * 使用netty提供的解码器类(LengthFieldBasedFrameDecoder)来解决粘包半包问题
     * <p>
     * 参数说明：
     * 参数1：maxFrameLength -  帧的最大长度，如果超过这个长度还没有发现分割的标准就会抛出 TooLongFrameException 异常
     * 参数2：lengthFieldOffset - 消息内容中记录内容长度部分信息的开始位置，例如：该字段是0，则表示从头开始
     * 参数3：LengthFieldlength - 消息内容中记录内容长度部分信息的长度，例如：该字段是2，则表示 记录长度的信息使用2个字节
     * +---------+---------------+
     * | length | Actual Content |    该消息总长14个字节，长度 占 2 个字节；消息内容 占 12 个字节
     * | 0x000c | "HELLO, WORLD" |
     * +---------+---------------+
     * 参数4：initialBytesToStrip - 从头剥离几个字节，就是在解码后的结果内容上从头开始去掉指定字节长度数量，例如上面的例子，想要去掉长度(length)部分，该字段可设置为2，去掉后内容如下
     * +-----------------+
     * | Actual Content |
     * | "HELLO, WORLD" |
     * +----------------+
     *
     * 参数5：lengthAdjustment - 以长度字段为基准，还有几个字节是内容
     */

    public static void main(String[] args) {
        EmbeddedChannel channel = new EmbeddedChannel(
                // 添加handler
                // 基于长度字段的解码器
//                new LengthFieldBasedFrameDecoder(1024,0,4,0,0), // 不剥离处理后的结果
//                new LengthFieldBasedFrameDecoder(1024,0,4,0,4), // 处理后的结果，从头开始剥离4个字节
                new LengthFieldBasedFrameDecoder(1024,0,4,1,0), // 以长度字段为基准，还有 1 个字节是内容
                new LoggingHandler(LogLevel.DEBUG)
        );

        // 4 个字节的内容长度，实际内容
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
        send(buffer, "Hello, world");
        send(buffer, "Hi!");
        // 向channel中写入消息
        channel.writeInbound(buffer);

    }

    private static void send(ByteBuf buffer, String content) {
        buffer.writeInt(content.length()); // 向buffer中写入内容长度
        buffer.writeByte(1); // 向buffer中写入额外的 1 个字节
        buffer.writeBytes(content.getBytes()); // 向buffer中写入内容
    }

}
